package com.bien.springboot.config;

import com.bien.springboot.constant.CasConstant;
import com.bien.springboot.filter.login.AdapterAuthenticationFilter;
import com.bien.springboot.filter.logout.AdapterLogoutFilter;
import com.bien.springboot.property.SpringCasProperty;
import org.jasig.cas.client.session.SingleSignOutHttpSessionListener;
import org.jasig.cas.client.util.AssertionThreadLocalFilter;
import org.jasig.cas.client.util.HttpServletRequestWrapperFilter;
import org.jasig.cas.client.validation.Cas20ProxyReceivingTicketValidationFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.boot.web.servlet.ServletListenerRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class CasConfig {

    @Autowired
    SpringCasProperty autoconfig;

    /**
     * 用于实现单点登出功能监听器
     */
    @Bean
    public ServletListenerRegistrationBean<SingleSignOutHttpSessionListener> singleSignOutHttpSessionListener() {
        ServletListenerRegistrationBean<SingleSignOutHttpSessionListener> listener = new ServletListenerRegistrationBean<>();
        listener.setEnabled(autoconfig.getEnabled());
        listener.setListener(new SingleSignOutHttpSessionListener());
        listener.setOrder(1);
        return listener;
    }

    /**
     * 该过滤器用于实现单点登出功能，单点退出配置，一定要放在其他filter之前
     */
    @Bean
    public FilterRegistrationBean singleSignOutFilter() {
        FilterRegistrationBean filterRegistration = new FilterRegistrationBean();
//        filterRegistration.setFilter(new SingleSignOutFilter());
        filterRegistration.setFilter(new AdapterLogoutFilter());
        filterRegistration.setEnabled(autoconfig.getEnabled());
        if (autoconfig.getLogout().getSignOutFilters().size() > 0) {
            filterRegistration.setUrlPatterns(autoconfig.getLogout().getSignOutFilters());
        } else {
            filterRegistration.addUrlPatterns(CasConstant.ALL_PATH);
        }
        filterRegistration.addInitParameter(CasConstant.CAS_SERVER_URL_PREFIX, autoconfig.getLogin().getCasServerUrlPrefix());
        filterRegistration.addInitParameter(CasConstant.SERVER_NAME, autoconfig.getLogin().getServerName());
        //自定义
        filterRegistration.addInitParameter(CasConstant.CAS_SERVER_LOGIN_URL, autoconfig.getLogin().getCasServerLoginUrl());
        filterRegistration.addInitParameter(CasConstant.CAS_SERVER_LOGOUT_URL, autoconfig.getLogout().getCasServerLogoutUrl());
        filterRegistration.addInitParameter(CasConstant.CAS_SERVER_LOGOUT_AFTER_URL, autoconfig.getLogout().getCasServerLogoutAfterUrl());
        filterRegistration.setOrder(2);
        return filterRegistration;
    }

    /**
     * 该过滤器负责用户的认证工作
     */
    @Bean
    public FilterRegistrationBean authenticationFilter() {
        FilterRegistrationBean filterRegistration = new FilterRegistrationBean();
//        filterRegistration.setFilter(new AuthenticationFilter());
        filterRegistration.setFilter(new AdapterAuthenticationFilter());
        filterRegistration.setEnabled(autoconfig.getEnabled());
        if (autoconfig.getLogin().getAuthFilters().size() > 0) {
            filterRegistration.setUrlPatterns(autoconfig.getLogin().getAuthFilters());
        } else {
            filterRegistration.addUrlPatterns(CasConstant.ALL_PATH);
        }
        //casServerLoginUrl:cas服务的登陆url
        filterRegistration.addInitParameter(CasConstant.CAS_SERVER_LOGIN_URL, autoconfig.getLogin().getCasServerLoginUrl());
        //本项目登录ip+port
        filterRegistration.addInitParameter(CasConstant.SERVER_NAME, autoconfig.getLogin().getServerName());
        filterRegistration.addInitParameter(CasConstant.USER_SESSION, autoconfig.getLogin().isUseSession() ? "true" : "false");
        filterRegistration.addInitParameter(CasConstant.REDIRECT_AFTER_VALIDATION, autoconfig.getLogin().isRedirectAfterValidation() ? "true" : "false");
        //自定义
        filterRegistration.addInitParameter(CasConstant.IGNORE_PATTERN, autoconfig.getIgnorePatternFiltersString());//eg:/js/*|/img/*|/view/*|/css/*
        filterRegistration.setOrder(3);
        return filterRegistration;
    }

    /**
     * 该过滤器负责对Ticket的校验工作
     */
    @Bean
    public FilterRegistrationBean cas20ProxyReceivingTicketValidationFilter() {
        FilterRegistrationBean filterRegistration = new FilterRegistrationBean();
        Cas20ProxyReceivingTicketValidationFilter cas20ProxyReceivingTicketValidationFilter = new Cas20ProxyReceivingTicketValidationFilter();
        cas20ProxyReceivingTicketValidationFilter.setServerName(autoconfig.getLogin().getServerName());
        filterRegistration.setFilter(cas20ProxyReceivingTicketValidationFilter);
        filterRegistration.setEnabled(autoconfig.getEnabled());
        if (autoconfig.getLogin().getValidateFilters().size() > 0) {
            filterRegistration.setUrlPatterns(autoconfig.getLogin().getValidateFilters());
        } else {
            filterRegistration.addUrlPatterns(CasConstant.ALL_PATH);
        }
        filterRegistration.addInitParameter(CasConstant.CAS_SERVER_URL_PREFIX, autoconfig.getLogin().getCasServerUrlPrefix());
        filterRegistration.addInitParameter(CasConstant.SERVER_NAME, autoconfig.getLogin().getServerName());
        filterRegistration.setOrder(4);
        return filterRegistration;
    }


    /**
     * 该过滤器对HttpServletRequest请求包装， 可通过HttpServletRequest的getRemoteUser()方法获得登录用户的登录名
     */
    @Bean
    public FilterRegistrationBean httpServletRequestWrapperFilter() {
        FilterRegistrationBean filterRegistration = new FilterRegistrationBean();
        filterRegistration.setFilter(new HttpServletRequestWrapperFilter());
        filterRegistration.setEnabled(autoconfig.getEnabled());
        if (autoconfig.getLogin().getRequestWrapperFilters().size() > 0) {
            filterRegistration.setUrlPatterns(autoconfig.getLogin().getRequestWrapperFilters());
        } else {
            filterRegistration.addUrlPatterns(CasConstant.ALL_PATH);
        }
        filterRegistration.setOrder(5);
        return filterRegistration;
    }

    /**
     * 该过滤器使得可以通过org.jasig.cas.client.util.AssertionHolder来获取用户的登录名。
     * 比如AssertionHolder.getAssertion().getPrincipal().getName()。
     * 这个类把Assertion信息放在ThreadLocal变量中，这样应用程序不在web层也能够获取到当前登录信息
     */
    @Bean
    public FilterRegistrationBean assertionThreadLocalFilter() {
        FilterRegistrationBean filterRegistration = new FilterRegistrationBean();
        filterRegistration.setFilter(new AssertionThreadLocalFilter());
        filterRegistration.setEnabled(autoconfig.getEnabled());
        if (autoconfig.getLogin().getAssertionFilters().size() > 0) {
            filterRegistration.setUrlPatterns(autoconfig.getLogin().getAssertionFilters());
        } else {
            filterRegistration.addUrlPatterns(CasConstant.ALL_PATH);
        }
        filterRegistration.setOrder(6);
        return filterRegistration;
    }
}